package cn.anlab.anappframe.net.sub2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.json.JSONException;
import org.json.JSONObject;

import android.os.Handler;

public class Controller {
	
	private static ExecutorService es;
	private static IConnection conn;
	
	private InetSocketAddress address;
	
	private Map<Integer, ReqCallback> callbackMap;
	
	private static Controller controller;
	
	public synchronized static Controller getInstance() {
		if(controller == null) {
			controller = new Controller(null);			//FIXME
		}
		return controller;
	} 
	
	public Controller(InetSocketAddress address) {
		this.address = address;
		this.callbackMap = new ConcurrentHashMap<Integer, ReqCallback>();
		if(es == null) {
			 es = Executors.newSingleThreadExecutor();
		}
		if(conn == null || !conn.isConnected()) {
			conn = new TCPConnection(address, handler);
		}
		conn.setHandler(handler);
		es.submit(new Runnable() {
			@Override
			public void run() {
				try {
					conn.connect();
				} catch (IOException e) {
					handler.onError(e);
				}
			}
		});
		
	}
	
//	/**
//	 * 
//	 * @param inter
//	 * @param method
//	 * @param params
//	 * @param handler
//	 */
//	public void process(Class inter, String method, Map params, Handler handler) {
//		
//	}
	
	
	/**
	 * 发送包
	 * @param outPacket
	 */
	public void send(OutPacket outPacket, ReqCallback callback) {
		if(!conn.isConnected()) {
			try {
				conn.connect();
			} catch (IOException e) {
				handler.onError(e);
			}
		}
		byte[] data = outPacket.getAllBytes();
		try {
			callbackMap.put(outPacket.getRc(), callback);
			conn.send(data);
		} catch (IOException e) {
			handler.onError(e);
		}
	}
	
	private void receive(InPacket inPacket) {
		Integer rc = inPacket.getRc();
		if( !callbackMap.containsKey(rc)) {
			System.out.println("no response.");
			return;
		}	
		ReqCallback callback = callbackMap.get(rc);
		callback.onReceive(inPacket);
	}

	private IHandler handler = new IHandler() {
		
		@Override
		public boolean onReceive(byte[] data) throws IOException {
			String content = new String(data);
			InPacket inPacket = null;
			try {
				JSONObject json = new JSONObject(content);
				int cmd = json.getInt("cmd");			
				int rc = json.getInt("rc");	
				Object obj = json.get("data");
				byte[] body = obj.toString().getBytes();
				inPacket = new InPacket(cmd, rc, body);
			} catch (JSONException e) {
				handler.onError(e);
			}
			receive(inPacket);
			return true;
		}
		
		@Override
		public boolean onError(Exception e) {
			e.printStackTrace();
			return false;
		}
		
		@Override
		public boolean onDisconnect() throws IOException {
			return false;
		}
		
		@Override
		public boolean onConnect() throws IOException {
			return false;
		}
	};
	
	public static void main(String[] args) {
		
		InetSocketAddress address = new InetSocketAddress("192.168.8.66", 7100);
		Controller req = new Controller(address);
		
		OutPacket op = new OutPacket(1, 2, "HelloWorld");
		ReqCallback callback = new ReqCallback() {
			@Override
			public void onReceive(InPacket inPacket) {
				String content = inPacket.getContent();
				System.out.println("receive content : " + content);
			}
		};
		req.send(op, callback);
		
	}
	

}
